package cz.proks.schoolpupilbook.gwt.core.handler;

import java.util.LinkedList;

import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Panel;

import cz.proks.schoolpupilbook.gwt.core.CookieHelper;
import cz.proks.schoolpupilbook.gwt.core.ResultNotifiable;
import cz.proks.schoolpupilbook.gwt.service.ListService;
import cz.proks.schoolpupilbook.gwt.service.ServiceFactory;
import cz.proks.schoolpupilbook.gwt.widget.common.CourseForm;
import cz.proks.schoolpupilbook.gwt.widget.common.MarkForm;
import cz.proks.schoolpupilbook.gwt.widget.common.UserCourseRelationForm;
import cz.proks.schoolpupilbook.gwt.widget.common.UserForm;
import cz.proks.schoolpupilbook.gwt.widget.common.UserRelationForm;
import cz.proks.schoolpupilbook.gwt.widget.form.course.CourseWidget;
import cz.proks.schoolpupilbook.gwt.widget.form.mark.MarkWidget;
import cz.proks.schoolpupilbook.gwt.widget.form.user.UserWidget;
import cz.proks.schoolpupilbook.gwt.widget.form.userCourseRelation.UserCourseRelationWidget;
import cz.proks.schoolpupilbook.gwt.widget.form.userRelation.UserRelationWidget;
import cz.proks.schoolpupilbook.gwt.widget.lector.LectorWidget;
import cz.proks.schoolpupilbook.gwt.widget.login.LoginWidget;
import cz.proks.schoolpupilbook.gwt.widget.parent.ParentWidget;
import cz.proks.schoolpupilbook.gwt.widget.student.StudentWidget;
import cz.proks.schoolpupilbook.shared.Constants;
import cz.proks.schoolpupilbook.shared.domain.Course;
import cz.proks.schoolpupilbook.shared.domain.User;
import cz.proks.schoolpupilbook.shared.domain.User.Role;

public class HistoryChangeHandler implements ValueChangeHandler<String> {
	private Panel panel;
	
	public HistoryChangeHandler(Panel panel) {
		super();
		this.panel = panel;
	}

	@Override
	public void onValueChange(ValueChangeEvent<String> event) {
		String historyToken = event != null ? event.getValue() : null;
		HistoryToken token = HistoryToken.forToken(historyToken);
		User user = getUserFromCookie();				
		IsWidget widget = null;
		
		if (token == HistoryToken.LOGIN && user != null) {
			History.newItem(getDefaultStateForUser(user));
			return;
		}
		
		switch (token) {
			default:
			case LOGIN:
				widget = loadLoginWidget(user);				
				break;
			
			case LOGOUT:
				doLogout();
				return;			
			
			case STUDENT:				
				widget = loadStudentWidget(user);
				break;
				
			case PARENT: 
				widget = loadParentWidget(user);
				break;
				
			case LECTOR:
				widget = loadLectorWidget(user);
					break;
					
			case USER_EDIT:
				widget = loadUserFormWidget(user, true);				
				break;
				
			case COURSE_EDIT:
				widget =  loadCourseFormWidget(user, true);
				break;
				
			case MARK_EDIT:
				widget = loadMarkFormWidget(user, true);
				break;
				
			case USER_RELATION_EDIT:
				widget = loadUserRelationFormWidget(user, true);
				break;
				
			case USER_COURSE_RELATION_EDIT:
				widget = loadUserCourseRelationWidget(user, true);
				break;
				
			case USER_NEW:
				widget = loadUserFormWidget(user, false);				
				break;
				
			case COURSE_NEW:
				widget =  loadCourseFormWidget(user, false);
				break;
				
			case MARK_NEW:
				widget = loadMarkFormWidget(user, false);
				break;
				
			case USER_RELATION_NEW:
				widget = loadUserRelationFormWidget(user, false);
				break;
				
			case USER_COURSE_RELATION_NEW:
				widget = loadUserCourseRelationWidget(user, false);
				break;
		}
		
		loadWidget(widget);
	}
	
	private User getUserFromCookie() {		
		return CookieHelper.getLoggedUser();
	}
	
	private String getDefaultStateForUser(User user) {
		if (user == null)
			return Constants.History.LOGIN;
		
		switch (user.getRole()) {
			case STUDENT: return Constants.History.STUDENT;					
			case PARENT: return Constants.History.PARENT;								
			case LECTOR: return Constants.History.LECTOR;			
			default: return null;
		}
	}
	
	private void doLogout() {
		Cookies.setCookie(Constants.Cookie.USER_LOGGED, "false");
		History.newItem("");
	}
	
	private void loadWidget(IsWidget widget) {
		panel.clear();
		panel.add(widget);
	}
	
	private IsWidget loadLoginWidget(User user) {										
		return new LoginWidget();		
	}
	
	private IsWidget loadStudentWidget(User user) {
		if (user == null)
			return loadLoginWidget(user);
		
		StudentWidget student = new StudentWidget(user);
		student.getLoggedUserPanel().setUserFullName(user.getFullName());		
		
		return student;
	}	
	
	private IsWidget loadParentWidget(User user) {
		if (user == null)
			return loadLoginWidget(user);
		
		ParentWidget parentWidget = new ParentWidget(user);
		parentWidget.getLoggedUserPanel().setUserFullName(user.getFullName());
		
		return parentWidget;
	}
	
	private IsWidget loadLectorWidget(User user) {
		LectorWidget lectorWidget = new LectorWidget();
		
		lectorWidget.getLoggedUserPanel().setUserFullName(user.getFullName());
		
		return lectorWidget;
	}
	
	private IsWidget loadUserFormWidget(User user, boolean edit) {
		UserWidget userWidget = new UserWidget();				
		UserForm userForm = userWidget.getUserForm();
		
		if (edit) {
			userForm.setId(user.getId());
			userForm.setName(user.getName());
			userForm.setSurname(user.getSurname());
			userForm.setLogin(user.getUsername());
			userForm.setPassword(user.getPassword());
			userForm.setRoles(wrapUserRoles());
			userForm.setRole(user.getRole());
		} else {
			userForm.setRoles(wrapUserRoles());
		}
		
		userWidget.getLoggedUserPanel().setUserFullName(user.getFullName());
				
		return userWidget;
	}
	
	private IsWidget loadCourseFormWidget(User user, boolean edit) {
		CourseWidget courseWidget = new CourseWidget();
		CourseForm courseForm = courseWidget.getCourseForm();
		
		if (edit) {
			// NOP
		} else {
			
		}
		
		return courseWidget;
	}
	
	private IsWidget loadMarkFormWidget(User user, boolean edit) {
		MarkWidget markWidget = new MarkWidget();
		final MarkForm markForm = markWidget.getMarkForm();
		
		if (edit) {
			// NOP
		} else {
			ListService listService = ServiceFactory.getListService();					
			listService.listUsersByRole(Role.LECTOR, new ResultNotifiable<LinkedList<User>>() {				
				@Override
				public void onSucces(LinkedList<User> object) {
					markForm.setLectors(object);
				}
				
				@Override
				public void onError(Throwable t) {}
			});			
			
			listService.listCourses(new ResultNotifiable<LinkedList<Course>>() {				
				@Override
				public void onSucces(LinkedList<Course> object) {
					markForm.setCourses(object);
					
				}
				
				@Override
				public void onError(Throwable t) {}
			});
		}
		 
		return markWidget;
	}
	
	private IsWidget loadUserRelationFormWidget(User user, boolean edit) {
		UserRelationWidget userRelationWidget = new UserRelationWidget();
		final UserRelationForm userRelationForm = userRelationWidget.getUserRelationForm();
		
		if (edit) {
			// NOP
		} else {
			ListService listService = ServiceFactory.getListService();
			listService.listUsersByRole(Role.PARENT, new ResultNotifiable<LinkedList<User>>() {
				
				@Override
				public void onSucces(LinkedList<User> object) {
					userRelationForm.setParents(object);					
				}
				
				@Override
				public void onError(Throwable t) {}
			});
			
			
			listService.listUsersByRole(Role.STUDENT, new ResultNotifiable<LinkedList<User>>() {				
				@Override
				public void onSucces(LinkedList<User> object) {
					userRelationForm.setStudents(object);					
				}
				
				@Override
				public void onError(Throwable t) {}
			});
		}
		
		return userRelationWidget;
	}
	
	private IsWidget loadUserCourseRelationWidget(User user, boolean edit) {
		UserCourseRelationWidget userCourseRelationWidget = new UserCourseRelationWidget();
		final UserCourseRelationForm userCourseRelationForm = userCourseRelationWidget.getUserCourseRelationForm();
		
		if (edit) {
			// NOP
		} else {
			ListService listService = ServiceFactory.getListService();
			
			listService.listCourses(new ResultNotifiable<LinkedList<Course>>() {

				@Override
				public void onSucces(LinkedList<Course> object) {
					userCourseRelationForm.setCourses(object);					
				}

				@Override
				public void onError(Throwable t) {}				
			});
			
			listService.listUsersByRole(Role.STUDENT, new ResultNotifiable<LinkedList<User>>() {
				
				@Override
				public void onSucces(LinkedList<User> object) {
					userCourseRelationForm.setStudents(object);					
				}
				
				@Override
				public void onError(Throwable t) {}
			});
		}
		
		return userCourseRelationWidget;
	}
	
	private LinkedList<User.Role> wrapUserRoles() {
		LinkedList<User.Role> roleList = new LinkedList<User.Role>();
		for (User.Role role : User.Role.values()) {
			roleList.add(role);
		}
		
		return roleList;
	}
	
	private enum HistoryToken {
		LOGIN(Constants.History.LOGIN), LOGOUT(Constants.History.LOGOUT), STUDENT(Constants.History.STUDENT), 
		PARENT(Constants.History.PARENT), LECTOR(Constants.History.LECTOR),
		USER_EDIT(Constants.History.USER_EDIT), COURSE_EDIT(Constants.History.COURSE_EDIT), 
		MARK_EDIT(Constants.History.MARK_EDIT), USER_COURSE_RELATION_EDIT(Constants.History.USER_COURSE_RELATION_EDIT),
		USER_RELATION_EDIT(Constants.History.USER_RELATION_EDIT),
		USER_NEW(Constants.History.USER_NEW), COURSE_NEW(Constants.History.COURSE_NEW), 
		MARK_NEW(Constants.History.MARK_NEW), USER_COURSE_RELATION_NEW(Constants.History.USER_COURSE_RELATION_NEW),
		USER_RELATION_NEW(Constants.History.USER_RELATION_NEW);
		
		private String historyToken;
		
		private HistoryToken(String historyToken) {
			this.historyToken = historyToken;
		}
		
		public String getHistoryToken() {
			return historyToken;
		}
		
		public static HistoryToken forToken(String token) {
			if (LOGIN.getHistoryToken().equals(token))
				return LOGIN;
			
			else if (LOGOUT.getHistoryToken().equals(token))
				return LOGOUT;
			
			else if (STUDENT.getHistoryToken().equals(token))
				return STUDENT;
			
			else if (PARENT.getHistoryToken().equals(token))
				return PARENT;
			
			else if (LECTOR.getHistoryToken().equals(token))
				return LECTOR;
			
			else if (USER_EDIT.getHistoryToken().equals(token))
				return USER_EDIT;
			
			else if(COURSE_EDIT.getHistoryToken().equals(token))
				return COURSE_EDIT;
			
			else if (MARK_EDIT.getHistoryToken().equals(token))
				return MARK_EDIT;
			
			else if (USER_RELATION_EDIT.getHistoryToken().equals(token))
				return USER_RELATION_EDIT;
			
			else if (USER_COURSE_RELATION_EDIT.getHistoryToken().equals(token))
				return USER_COURSE_RELATION_EDIT;
			
			else if (USER_NEW.getHistoryToken().equals(token))
				return USER_NEW;
			
			else if(COURSE_NEW.getHistoryToken().equals(token))
				return COURSE_NEW;
			
			else if (MARK_NEW.getHistoryToken().equals(token))
				return MARK_NEW;
			
			else if (USER_RELATION_NEW.getHistoryToken().equals(token))
				return USER_RELATION_NEW;
			
			else if (USER_COURSE_RELATION_NEW.getHistoryToken().equals(token))
				return USER_COURSE_RELATION_NEW;
				
			else 
				return LOGIN;
		}
	}
}
